// elitenpc.txt
// by Nioca

// An improved form of improvednpc, by Walker M. White, whic is an improved
// form of the standard creature script basicnpc, by Jeff Vogel.

// There are two main differences between this script and it's predecessors.
// First, the script uses an advanced targeting system which makes
// a creature deadlier in combat. Secondly, you can micro-manage how the creature  
// moves and behaves. Also, you can change special abilities, creature levels, and 
// combat strategies, all by adjusting the memory cells.

// A full list of changes is located at the bottom of this script.

// Memory Cells:
//   Cell 0 - How creature moves.
//     0 - If 0, wander randomly. 
//     1 - Stands still until a target appears.
//     2 - Completely immobile, even if target appears.
//     0-299,0-29 - Set a flag to one when killed.
//     310-400,0-1 - Calls a state when killed. The state called is equal to
//        the number in cell 1, minus 300. If cell 2 is set to 0, calls a
//        state in the current town script. If set to 1, calls a state in
//        the scenario script.
//   Cell 3 - Dialogue node to start with if talked to. if left at 0, this
//     character doesn't talk.
//   Cell 4 - Level boost. When the creature is initialized, it's level will
//     be the base level for that creature type plus this number.
//   Cell 5 - Special Ability. When the creature is initialized, it will
//     receive the special ability specified in this cell. Valid
//     abilities to choose from are listed below.
//     0 - No ability/Default ability.
//     1 - Melee attack poisons target.
//     2 - Fires a ray that curses and weakens the target.
//     3 - Petrification. Has a chance of turning the target to stone.
//     4 - Melee attack slows target.
//     5 - Throws webs at the target. Has a maximum range of 4.
//     6 - Melee attack diseases target.
//     7 - Fires charm ray at target.
//     8 - Melee attack puts target to sleep.
//     9 - Fires sleep ray at target.
//     10 - Melee attack paralyzes target.
//     11 - Fires paralysis ray at target.
//     12 - Melee attack covers target with acid.
//     13 - Fires dumbfounding/spell point draining ray at target.
//     14 - Fires confusion ray at target.
//     15 - Fires terrify/enfeeble ray at target.
//     16 - Throws rocks, which do a fair amount of damage.
//     17 - Breathes fire at target.
//     18 - Breathes cold at target.
//     19 - Breathes acid at target.
//     20 - Melee attack does extra fire damage.
//     21 - Melee attack does extra cold damage.
//     22 - Melee attack drains experience.
//     23 - Melee attack does extra cold damage and drains experience.
//     24 - Creature is invisible. Can only be hit by melee attacks.
//     26 - Radiates a fire field.
//     27 - Radiates a cold field.
//     28 - Radiates an antimagic field.
//     29 - Divides in two when struck.
//     30 - Fires a fire ray at target.
//     32 - Fires an energy ray (magic damage) at target.
//     33 - Breathes darkness (damage + enfeeblement)
//     34 - Throws spines at target. Does good damage and paralyzes.
//     35 - Creates forcecage around target.
//     36 - Melee attack webs target.
//     37 - Radiates a sleep cloud.
//     38 - Radiates a stinking cloud.
//     39 - Radiates a blade field.
//   Cell 6 - Sets the creature strategy.
//     0 - Act normally.
//     1 - Fire missiles or use innate special ability.
//     2 - Cast spells.
//     3 - Use items in inventory.
//   Cell 7 - Extra item for creature. None if left at 0.
//   Cell 8 - Permanent status for creature.
//     0 - None.
//     1 - Poisoned.
//     2 - Blessed.
//     3 - Shielded.
//     4 - Hasted.
//     5 - Invulnerable.
//     6 - Magic Resistant.
//     7 - Webbed.
//     8 - Diseased.
//     9 - Charmed.
//     10 - Berserk.
//     11 - Asleep.
//     12 - Paralysed.
//     13 - Acidified.
//     14 - Dumbfounded.
//     15 - Sanctuary.
//     16 - Martyr's Shield.
//     17 - Divinely Touched.
//     18 - Resistant.
//     19 - Confused.
//     20 - Enlightened. This status is only used for special encounters.
//     21 - Terrified.
//     22 - Enfeebled.
//     23 - Regenerating.
//     24 - Nimble Fingers.
//     25 - Featherfall.
//     26 - Flying.
//     27 - Safe Travel.
//     28 - Hovering Feet.
//     29 - Drunk.
//     30 - Force Caged.
//     31 - Fleeing.
//     32 - Cursed.
//     33 - Weakened.
//     34 - Slowed.
//   Cell 9 - Sniper mode. If this is set to 1, the creature will scan every
//     turn for a new target. This is most useful for archers or spellcasters.

begincreaturescript;

variables;

short i,target,r,m;
short scan;
short melee_or_missile;

body;

beginstate INIT_STATE;

 	// Melee_or_missile checks whether the creature is a melee or missile combatant.
 	// This is important when scanning for targets.
 	if ((item_type_in_slot(my_number(),2) > 0) || (get_stat(ME,11) > 0) || (get_stat(ME,12) > 3))
	 	melee_or_missile = 1;
		
	// Now we set some important characteristics about myself.

	// Can I move?
	if (get_memory_cell(0) == 2)
		set_mobility(ME,0);

	// Do I recieve a level bonus?
	set_level(ME,get_level(my_number()) + get_memory_cell(4));

	// Do I get a special ability?
	if (get_memory_cell(5) > 0) 
		set_special_ability(ME,get_memory_cell(5));

	// Do I get a bonus item?
	if (get_memory_cell(7) > 0)
		char_give_item(ME,get_memory_cell(7));

	// Activate my permanent status, if I have one.
	if (get_memory_cell(8) > 0) {
		if (get_memory_cell(8) < 32)
			set_char_status(ME,get_memory_cell(8) - 1,250,1,0);
		if (get_memory_cell(8) == 33) 
			set_char_status(ME,1,-250,1,0);
		if (get_memory_cell(8) == 34)
			set_char_status(ME,2,-250,1,0);
		if (get_memory_cell(8) == 35)
			set_char_status(ME,3,-250,1,0);
		}

break;

beginstate DEAD_STATE;

	// What should happen when I die?
	// If cells 1 and 2 are 0, nothing.
	if (get_memory_cell(1) + get_memory_cell(2) == 0)
		end();

	// If cell 1 is less than 300, set a flag to 1.
	if (get_memory_cell(1) < 300) {
		set_flag(get_memory_cell(1),get_memory_cell(2),1);
		end(); }	

	// If cell 1 is a value between 310 and 400, call a state.
	if ((get_memory_cell(1) > 309) && (get_memory_cell(1) < 401)) {
		if (get_memory_cell(2) == 1)
			run_scenario_script(get_memory_cell(1) - 300);
		else run_town_script(get_memory_cell(1) - 300);
		}

break;

beginstate START_STATE;

	// Sustain my permanent status, if I have one.
	if (get_memory_cell(8) > 0) {
		if (get_memory_cell(8) < 32)
			set_char_status(ME,get_memory_cell(8) - 1,250,1,0);
		if (get_memory_cell(8) == 33) 
			set_char_status(ME,1,-250,1,0);
		if (get_memory_cell(8) == 34)
			set_char_status(ME,2,-250,1,0);
		if (get_memory_cell(8) == 35)
			set_char_status(ME,3,-250,1,0);
		}

	// Has one of my comrades found a target?
	if ((my_current_message() == 1) && (dist_to_party() < 18)) {
		alert_char(ME); }

        // If I have a target for some reason, go attack it
        if (target_ok()) {
                if (dist_to_char(get_target()) <= 16) {
			scan = get_current_tick();
			broadcast_char_message(8,1,1);
                        set_state(3); }
                else set_target(ME,-1);
		}

        // Have I been hit by nearby living creature? Strike back!
        if (who_hit_me() >= 0) {
                if (dist_to_char(who_hit_me()) <= 2 && char_ok(who_hit_me()) == TRUE) {	
                	set_target(ME,who_hit_me());
 			scan = get_current_tick();
			broadcast_char_message(8,1,1);
                	set_state(3);
                	}
        	}

        // If no one close, we defend ourselves against ranged attackers.
        if (who_hit_me() >= 0) {
                // Target may have been killed since it struck.
                if (char_ok(who_hit_me()) == TRUE) {
                        set_target(ME,who_hit_me());
			scan = get_current_tick();
			broadcast_char_message(8,1,1);
                        set_state(3);
                }
        }

        // Start looking for a target.

	if (melee_or_missile == 0) {
		r = 1;
		while (r < 8) {
	        	select_target(ME,r,2);
	        	if (target_ok() == FALSE)
	        		select_target(ME,r,1);
		        if (target_ok() == FALSE)
		        	select_target(ME,r,0);
			if (target_ok()) {
				scan = get_current_tick();
				broadcast_char_message(8,1,1);
				set_state(3); }
			r = r + 2; }
			}
	if (melee_or_missile == 1) {
		select_target(ME,8,2);
	        if (target_ok() == FALSE)
	       		select_target(ME,8,1);
		if (target_ok() == FALSE)
		        select_target(ME,8,0);
		if (target_ok()) {
			scan = get_current_tick();
			broadcast_char_message(8,1,1);
			set_state(3); }
			}

	// Finally, if I've been hit, but can't find a target, we hunt
	// down the attacker. (This undermines a popular strategy of
	// hasting an archer, having him fire into the room, and then
	// stepping back out so that the creature won't fight back.)
        if (who_hit_me() >= 0) {
                // Attacker may have been killed since it struck.
                if (char_ok(who_hit_me()) == TRUE) {
			approach_char(ME,who_hit_me(),0); }
		}


        // Otherwise, just peacefully move around.
        if ((my_dist_from_start() >= 6) || ((my_dist_from_start() > 0) && (get_memory_cell(0) > 0))) {
                if (get_ran(1,1,100) < 40) {
                        return_to_start(ME,1);
                }
        } else if (get_memory_cell(0) == 0) {
                fidget(ME,45);
        }

        // if we're in combat and the above didn't give me anything to do, just
        // stop now. Otherwise, game will keep running script, and that eats up CPU time.
        if (am_i_doing_action() == FALSE) {
                end_combat_turn();
        }
break;

beginstate 3; // attacking

	// Sustain my permanent status, if I have one.
	if (get_memory_cell(8) > 0) {
		if (get_memory_cell(8) < 32)
			set_char_status(ME,get_memory_cell(8) - 1,250,1,0);
		if (get_memory_cell(8) == 33) 
			set_char_status(ME,1,-250,1,0);
		if (get_memory_cell(8) == 34)
			set_char_status(ME,2,-250,1,0);
		if (get_memory_cell(8) == 35)
			set_char_status(ME,3,-250,1,0);
		}

	// Should I scan for a new target?
	if ((tick_difference(scan,get_current_tick()) > 3) || (get_memory_cell(9) > 0)) {
		if (melee_or_missile == 0) {
	        	select_target(ME,1,2);
	        	if (target_ok() == FALSE)
	        		select_target(ME,1,1);
	        	if (target_ok() == FALSE)
	        		select_target(ME,1,0);
	        	}
		}
	        if (melee_or_missile == 1) {
	        	select_target(ME,8,2);
	        	if (target_ok() == FALSE)
	        		select_target(ME,8,1);
	        	if (target_ok() == FALSE)
	        		select_target(ME,8,0);
	        	}
						
	// Is my current target ok?
        if (target_ok() == FALSE) {
		// Do I have another target nearby?
        	select_target(ME,2,2);
        	if (target_ok() == FALSE)
        		select_target(ME,2,1);
        	if (target_ok() == FALSE)
        		select_target(ME,2,0);
		// If I don't, go back to the start state.
        	if (target_ok())
                	set_state(START_STATE);
		else scan = get_current_tick();
        }
        do_attack_tactic(get_memory_cell(6));

break;

beginstate TALKING_STATE;

        if (get_memory_cell(3) > 0)
		begin_talk_mode(get_memory_cell(3));
	else print_str("Talking: It doesn't respond.");

break;


// Changes from improvednpc:

// Targeting order changed. Now the creature:
//	- Attacks its current target.
//	- Defends self from nearby living creatures.
//	- Defends self from ranged attackers.
//	- Looks for a target.
//	- Hunts down attackers.

// A new targeting system developed. Creatures will now go after targets
// 	that are heavily wounded before it targets a healthy creature.

// When the creature's target is killed, it sweeps the immediate area for
//	a new target, using the targeting system mentioned above.

// In combat, a creature will occasionally scan the area optimum targets,
//	even if it already has one.

// Creatures now have a built-in 'Sniper Mode.' When active, the creature will
//	scan for targets every turn. This was made to improve the effectiveness
//	of archers, spellcasters, and special abilities.

// A melee character will prefer targets that are closer to it, rather than
//	one across the room.

// A character will broadcast a message when it finds a target, and any nearby
//	characters using this script will be alerted that an enemy is nearby.

// New memory cells that can be used to increase the level of a creature, give
// 	it a special ability, change its strategy, give it an item, or grant
//	a permanent status.

// A new death state, which lets a designer choose between setting a flag or
//	calling a special.